#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QtConcurrent>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    mutex = new QMutex();
    wait = new QWaitCondition();
    table = new QStandardItemModel(this);
    table->setColumnCount(3);
    table->setHeaderData(0,Qt::Horizontal, "N");
    table->setHeaderData(1,Qt::Horizontal, "解的个数");
    table->setHeaderData(2,Qt::Horizontal, "时间消耗");
    ui->tableView->setModel(table);

    solver = new EightQueenSolver(ui->spin_N->value(),mutex,wait);
    solver->setAutoDelete(false);   // 线程管理：任务结束后不自动删除
    multiSolver = new MultiThreadSolver(ui->spin_N->value());

    normalMode();

    connect(solver,SIGNAL(finish()),this ,SLOT(showCalcData()));
    connect(solver,SIGNAL(stopped()),this ,SLOT(showStopData()));
    connect(solver,SIGNAL(stepped()),this ,SLOT(showStopData()));
    connect(solver,SIGNAL(oneResult()),this,SLOT(updateBoard()));
    connect(ui->btn_calc,SIGNAL(clicked()),this,SLOT(calc()));
    connect(ui->btn_stop,SIGNAL(clicked()),this,SLOT(stop()));
    connect(ui->btn_pause,SIGNAL(clicked()),this,SLOT(pause()));
    connect(ui->btn_singleStep,SIGNAL(clicked()),this,SLOT(singleStep()));
    connect(ui->spin_N,SIGNAL(valueChanged(int)),this,SLOT(spinN(int)));
    connect(ui->mode_normal,SIGNAL(clicked()),this,SLOT(normalMode()));
    connect(ui->mode_singleStep,SIGNAL(clicked()),this,SLOT(singleStepMode()));
    connect(ui->mode_multiThread,SIGNAL(clicked()),this,SLOT(multiThreadMode()));
    connect(ui->btn_multiThread,SIGNAL(clicked()),this,SLOT(multiCalc()));
    connect(multiSolver,SIGNAL(oneResult()),this,SLOT(updateBoard()));
    connect(multiSolver,SIGNAL(finished()),this ,SLOT(showCalcData()));
    connect(multiSolver,SIGNAL(stopped()),this ,SLOT(showStopData()));
    connect(ui->checkBox,SIGNAL(stateChanged(int)),solver,SLOT(setResOnly(int)));

    spinN(ui->spin_N->value());
}



MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::spinN(int n)
{
    stop();
    solver->setN(n);
    multiSolver->setN(n);
    ui->DrawBoard->setN(n);
    ui->DrawBoard->setBoard(solver->lastRes);
    updateBoard();
}

void MainWindow::solve()
{
    // 在另一线程上执行求解函数
    QThreadPool::globalInstance()->start(solver);

    ui->label_resnum->setText("正在拼命计算中……ﾍ( ﾟ∀ﾟ;)ﾉ");
    ui->label_time->setText("正在拼命计算中……ﾍ( ﾟ∀ﾟ;)ﾉ");
    ui->btn_pause->setText("暂停");
    ui->DrawBoard->update();
}

void MainWindow::updateBoard()
{
    ui->DrawBoard->update();
}

void MainWindow::normalMode()
{
    stop();
    m_mode = NORMAL;
    ui->DrawBoard->setBoard(solver->lastRes);
    ui->btn_calc->setEnabled(true);
    ui->btn_pause->setEnabled(true);
    ui->btn_singleStep->setEnabled(false);
    ui->checkBox->setEnabled(false);
    ui->btn_multiThread->setEnabled(false);
}

void MainWindow::singleStepMode()
{
    stop();
    m_mode = SINGLE_STEP;
    ui->DrawBoard->setBoard(solver->lastRes);
    ui->btn_calc->setEnabled(false);
    ui->btn_pause->setEnabled(false);
    ui->btn_singleStep->setEnabled(true);
    ui->checkBox->setEnabled(true);
    ui->btn_multiThread->setEnabled(false);
}

void MainWindow::multiThreadMode()
{
    stop();
    m_mode = MULTI_THREAD;
    ui->btn_calc->setEnabled(false);
    ui->btn_pause->setEnabled(false);
    ui->btn_singleStep->setEnabled(false);
    ui->checkBox->setEnabled(false);
    ui->btn_multiThread->setEnabled(true);
}

void MainWindow::pause()
{
    if(solver->isStop()) return;
    solver->pauseSolve();
    solver->step=false;
    if(solver->isPause()) ui->btn_pause->setText("继续");
    else {
        wait->wakeAll();
        ui->btn_pause->setText("暂停");
    }
}

void MainWindow::stop()
{
    solver->stopSolve();
    wait->wakeAll();
    pause();

    multiSolver->stopSolve();
}

void MainWindow::singleStep()
{
    solver->step=true;
    if(solver->isStop()) {
        solve();
    }
    else{
        wait->wakeAll();
    }
}


void MainWindow::showCalcData()
{
    QString n;
    QString res;
    QString t;
    if(m_mode!=MULTI_THREAD){
        n=QString::number(solver->getN());
        res=QString::number(solver->getResNum());
        t=QString::number(solver->getTime());
    }else{
        n=QString::number(multiSolver->getN());
        res=QString::number(multiSolver->getResNum());
        t=QString::number(multiSolver->getTime());
    }
    ui->label_resnum->setText(n+"皇后问题共有"+res+"个解");
    ui->label_time->setText("计算用时："+t+"s");
    // 添加记录
    QList<QStandardItem*> list;
    list << new QStandardItem(n) << new QStandardItem(res) << new QStandardItem(t);
    table->insertRow(table->rowCount(),list);
}

void MainWindow::showStopData()
{
    QString n;
    QString res;
    QString t;
    if(m_mode!=MULTI_THREAD){
        n=QString::number(solver->getN());
        res=QString::number(solver->getResNum());
        t=QString::number(solver->getTime());
    }else{
        n=QString::number(multiSolver->getN());
        res=QString::number(multiSolver->getResNum());
        t=QString::number(multiSolver->getTime());
    }
    ui->label_resnum->setText(n+"皇后问题 已找到"+res+"个解");
    ui->label_time->setText("计算用时："+t+"s");
}

void MainWindow::calc()
{
    // 将保存解的棋盘的地址传给画板
    ui->DrawBoard->setBoard(solver->lastRes);
    if(solver->step==true){
        stop();
        wait->wakeAll();
    }else{
        solver->step=false;
        solve();
    }
}

void MainWindow::multiCalc()
{
    stop();
    // 将保存解的棋盘的地址传给画板
    ui->DrawBoard->setBoard(multiSolver->lastRes);
    QFuture<void> f = QtConcurrent::run(&MultiThreadSolver::solve,multiSolver);

    ui->label_resnum->setText("正在拼命计算中……ﾍ( ﾟ∀ﾟ;)ﾉ");
    ui->label_time->setText("正在拼命计算中……ﾍ( ﾟ∀ﾟ;)ﾉ");
    ui->btn_pause->setText("暂停");
    ui->DrawBoard->update();
}

